<template>
  <el-upload
    class="my-upload"
    :class="disabled ? 'is-disabled' : ''"
    v-model:file-list="fileList"
    :list-type="listType"
    :http-request="httpRequest"
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :on-success="handleSuccess"
    :on-error="handleError"
    :on-progress="handleProgress"
    :on-change="handleChange"
    :on-exceed="handleExceed"
    :before-upload="beforeUpload"
    :before-remove="beforeRemove"
    :multiple="props.multiple"
    :limit="props.limit"
    :disabled="props.disabled"
  >
    <template v-if="!props.disabled">
      <el-button v-if="isFile" type="primary">上传文件 </el-button>
      <i-ep-plus v-else></i-ep-plus>
    </template>

    <el-button
      v-if="isFile && config?.fileTemplateUrl"
      text
      type="info"
      @click.stop="onDownloadTemplate(config!.fileTemplateUrl!, prop)"
    >
      模板下载
    </el-button>

    <template #file="{ file }" v-if="isFile">
      <div class="file-list-item">
        <span class="text-hidden">{{ file.name }}</span>
        <template v-if="file.status === 'success'">
          <el-icon color="green">
            <CircleCheck />
          </el-icon>
          <span text type="info" @click="onPreviewFile(file)"> 预览 </span>
          <span text class="ml-5px" type="info" @click="onDownloadFile(file)">
            下载
          </span>
          <span
            class="delete-btn"
            @click="onRemoveFile(file)"
            v-if="!props.disabled"
            >删除</span
          >
        </template>
        <!--loading-->
        <template v-else>
          <el-icon class="loading-icon" :size="17">
            <Loading />
          </el-icon>
        </template>
      </div>
    </template>

    <template #tip>
      <div
        class="el-upload__tip tip-text text-red"
        v-if="config?.tipText && !disabled"
      >
        {{ config?.tipText }}
      </div>
    </template>
  </el-upload>
  <el-image-viewer
    v-if="showImgViewer"
    :url-list="imagePreviewUrls"
    :onClose="closeImgViewer"
    :z-index="3000"
    :initial-index="initialImgPreviewIndex"
  />
</template>

<script setup lang="ts">
// import api from '@/api';
// import { useMessage } from '@/composables';
// import { FormPropType, UploadResponse, UploadReturnType } from '@/types';
import type {
  UploadFile,
  UploadFiles,
  UploadProgressEvent,
  UploadProps,
  UploadRawFile,
  UploadRequestOptions,
  UploadUserFile
} from 'element-plus';
import { PropType, ref, watch } from 'vue';
import { saveAs } from 'file-saver';
// import { downloadFileUp, previewFile } from '@/utils';
// import { acceptFile } from '@/views/law/components/myUploadAcceptFile';

const { handleWarning, handleDeleteConfirm } = useMessage();
const props = defineProps({
  modelValue: {
    type: Array as PropType<UploadResponse[] | string[]>
  },
  itemProp: {
    type: Object as PropType<FormPropType>,
    required: true
  },
  multiple: {
    type: Boolean as PropType<boolean>,
    default: false
  },
  limit: {
    type: Number as PropType<number>,
    default: 1
  },
  tipText: {
    type: String as PropType<string>,
    default: ''
  },
  disabled: {
    type: Boolean as PropType<boolean>,
    default: false
  },

  originFilesStr: {
    type: String as PropType<string>,
    default: ''
  },
  returnType: {
    type: String as PropType<UploadReturnType>,
    default: 'fileObject'
  },
  formRef: {
    type: Object as PropType<any>
  }
});
const emit = defineEmits<{
  // (e: "setUpload", refs: { [x: string]: any }, files: UploadUserFile[]): void;
  (e: 'setUpload', fileList: UploadResponse[] | string[], name: string): void;
  (e: 'update:modelValue', data: UploadResponse[] | string[]): void;
  (e: 'setDeleteFileId', data: string): string;
}>();

const scopeData = computed<any>({
  get() {
    console.log('MyFormUpload-scopeData', props.modelValue);
    return props.modelValue;
  },
  set(data: UploadResponse[] | string[]) {
    if (data && data.length > 0) props.formRef?.clearValidate(prop.value.name);

    emit('update:modelValue', data);
  }
});

// console.log('disabled', props.disabled);
const ACCEPT_PHOTO = ['image/jpeg', 'image/jpg', 'image/png'];
// const ACCEPT_FILE = [
//   '.doc',
//   '.docx',
//   'application/msword',
//   'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
//   '.pdf',
//   'application/pdf',
//   ...ACCEPT_PHOTO
// ];
const ACCEPT_FILE = [...acceptFile, ...ACCEPT_PHOTO];
const ONLY_FILE_TIP = '只能上传 DOC、DOCX、JPG、JPEG、PDF、PNG 格式文件';
const ONLY_PHOTO_TIP = '只能上传 JPG、JPEG、PNG 格式图片';

const prop = computed(() => props.itemProp);
const name = computed(() => props.itemProp.name);
const config = computed(() => props.itemProp.uploadConfig);
const isFile = computed(() => prop.value.type === 'upload-file');
const listType = computed<'picture-card' | 'text' | 'picture'>(() => {
  if (isFile.value) return 'text';
  return 'picture-card';
});
const imagePreviewUrls = ref<any[]>([]);
const initialImgPreviewIndex = ref(0);
const showImgViewer = ref(false);

/* 下载模板 */
function onDownloadTemplate(path: string, prop?: FormPropType) {
  console.log('onDownloadTemplate: ', path, prop);
  saveAs(path, prop?.label);
}

/* 下载文件 */
function onDownloadFile(file: UploadFile) {
  console.log(file);
  const { name, url } = file;
  console.log('onDownloadFile--: ', name, url);
  if (!url) {
    handleWarning('文件地址获取失败');
    return;
  }
  downloadFileUp(url, name);
  // saveAs(url, name);

  // if (!file) {
  //   const url = getUploadUrl(file);
  //   const name = file?.name;
  // }
}

function getReturnFileData(data: UploadResponse[]) {
  const returnFnTypeMap = {
    string: returnStringFileData,
    fileObject: returnFileObjectFileData
  };
  return returnFnTypeMap[props.returnType](data);
}

// 返回字符串格式文件数据
function returnStringFileData(data: UploadResponse[]): string[] {
  return data.map(item => item.url);
}

// 返回文件对象格式文件数据
function returnFileObjectFileData(data: UploadResponse[]): UploadResponse[] {
  return data;
}

/* 预览文件 */
// function onPreviewFile(file?: UploadFile) {
//   if (file) {
//     const url = getUploadUrl(file);
//     console.log("onPreviewFile: ", url);
//   }

// const dom = document.querySelector(".content-docx") as HTMLElement;
//     renderAsync(docxData, dom).then(x => console.log("docx: finished", x));

//   fileList.value.map(item => {
//     const url = getUploadUrl(item);
//     if (url) {
//       renderAsync(url).then(res => {
//         console.log("onPreviewFile: ", res);
//         dialogImageUrl.value = res.url;
//         dialogVisible.value = true;
//       });
//     }
//   });
// }

/* 删除文件 */
async function onRemoveFile(file: UploadFile) {
  const confirmResult = await handleDeleteConfirm();
  if (!confirmResult) return;
  removeFileAndEmit(file);
  // const url = getUploadUrl(file);
  // emit("setUpload", arr, name.value);
}

function onPreviewFile(file: UploadFile) {
  previewFile(file.url as string);
  console.log(file);
}

function removeFileAndEmit(file: UploadFile) {
  const { uid, url, response } = file;
  const { objectName } = (response as { objectName: string }) || {};
  fileList.value = fileList.value.filter(item => item.uid !== uid);
  scopeData.value = getReturnFileData(
    fileList.value.map(item => item.response) as UploadResponse[]
  );
  emit('setDeleteFileId', objectName);
  // emit(
  //   'setUpload',
  //   fileList.value.map(item => item.url) as string[],
  //   name.value
  // );
}

function splitObjectFiles(url: string, split = '') {
  return url.substring(url.lastIndexOf(split) + split.length, url.length);
}

function splitFiles(str: string) {
  if (!str) return [];

  return str.split(',').map(v => {
    // http://47.107.76.169:9000/dev/2022/07/20/微信截图_20220718111228.png
    const _name = v.split('/').slice(-1)[0];
    return {
      name: _name, // 微信截图_20220718111228.png
      url: v
    };
  });
}

const dialogVisible = ref(false);
const dialogImageUrl = ref('');

const fileList = ref<UploadUserFile[]>(splitFiles(props.originFilesStr));
watch(
  () => props.modelValue,
  cur => {
    if (!cur) fileList.value = [];

    if (!Array.isArray(cur)) return;
    fileList.value =
      (cur
        ?.map(item => {
          if (typeof item === 'string') {
            return {
              name: item.split('/').slice(-1)[0], // 微信截图_20220718111228.png
              url: item
            };
          } else {
            if (item?.url) {
              return {
                url: item?.url,
                response: item as any,
                name: item?.fileName
              };
            }
          }
        })
        .filter(item => {
          if (item?.url) return true;
          else return false;
        }) as UploadUserFile[]) || [];
  },
  {
    immediate: true
  }
);

const httpRequest: UploadProps['httpRequest'] = (
  opts: UploadRequestOptions
) => {
  const can = new FormData();
  can.append('file', opts.file);

  return api.object.objectUploadPost(can);
};

const handlePreview: UploadProps['onPreview'] = (uploadFile: UploadFile) => {
  if (isFile.value) return;
  let index = imagePreviewUrls.value.indexOf(uploadFile.url);
  if (index >= 0) {
    initialImgPreviewIndex.value = index;
  } else {
    imagePreviewUrls.value.push(uploadFile.url);
    initialImgPreviewIndex.value = imagePreviewUrls.value.length - 1;
  }
  showImgViewer.value = true;
};

function closeImgViewer() {
  console.log('11111111111111111111111111');
  showImgViewer.value = false;
}

const handleRemove: UploadProps['onRemove'] = async (
  uploadFile,
  uploadFiles
) => {
  // const _url = getUploadUrl(uploadFile);

  // const url = splitObjectFiles(_url, "dev/");
  // const res = await api.object.objectDelete({ objectName: url });

  // FIXME: 删除无返回结果，不知道是否成功
  const arr = uploadFiles.map<string>(file => {
    return getUploadUrl(file);
  });

  removeFileAndEmit(uploadFile);

  // emit('setUpload', arr, name.value);

  // });
};

/* 获取上传文件的url */
function getUploadUrl(file: UploadFile) {
  if (file.response) return (file.response as any)?.url;
  else return file.url;
}

const handleSuccess: UploadProps['onSuccess'] = (
  response: any,
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  // console.log(uploadFiles);
  // console.log(name);
  const arr: UploadResponse[] = uploadFiles
    .map(file => {
      if (file.response) return file.response as UploadResponse;
      else return {} as UploadResponse;

      // if (file.response) return (file.response as UploadResponse) ?? null;
    })
    .filter(item => item);
  scopeData.value = getReturnFileData(arr);
  // emit('setUpload', arr, name.value);
};

const handleError: UploadProps['onError'] = (
  error: Error,
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  // ...
};

const handleProgress: UploadProps['onProgress'] = (
  event: UploadProgressEvent,
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  // ...
};

const handleChange: UploadProps['onChange'] = (
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  // ...
};

const handleExceed: UploadProps['onExceed'] = (
  files: File[],
  uploadFiles: UploadUserFile[]
) => {
  handleWarning(
    `限制 ${props.limit} 个文件，你当前已经有 ${uploadFiles.length} 个文件！！！`
  );
};

const isAccept = ref(true);
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
  // console.log('beforeUpload: ', rawFile);
  // console.log('}isFile.value : ', isFile.value);
  const _accept = config.value?.accept?.length
    ? config.value?.accept
    : isFile.value
    ? ACCEPT_FILE
    : ACCEPT_PHOTO;
  const _tip = config.value?.tipText
    ? config.value?.tipText
    : isFile.value
    ? ONLY_FILE_TIP
    : ONLY_PHOTO_TIP;
  isAccept.value = _accept.includes(rawFile.type);
  const isLt2M = rawFile.size / 1024 / 1024 < 2;

  if (!isAccept.value) {
    handleWarning(_tip);
    return false;
  }
  return true;
};

const beforeRemove: UploadProps['beforeRemove'] = (
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  if (!isAccept.value) {
    isAccept.value = true;
    return true;
  }
  return handleDeleteConfirm();
};

onMounted(() => {});
</script>

<style lang="scss" scoped>
:deep(.is-disabled .el-upload--picture-card) {
  cursor: not-allowed;
  display: none;
}

// FIXME: 表单校验图片边框错误样式，不生效
:deep(.is-error .el-upload--picture-card) {
  // :deep(.is-error) {
  border: 1px solid var(--el-color-danger) !important;
}

.file-list-item {
  display: flex;
  align-items: center;

  span {
    cursor: pointer;
    max-width: 80%;
  }

  .delete-btn {
    margin-left: 5px;
    color: #f56c6c;
  }

  i {
    margin-left: 3px;
    margin-right: 5px;
  }

  .loading-icon {
    animation: rotate 3s linear infinite;
  }
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

.description-text {
  display: block;
}

.tip-text:before {
  content: '*';
  font-size: 18px;
  float: left;
  margin-top: 3px;
}

.text-red {
  color: #f56c6c;
}
.my-upload {
  width: 100%;
}

.is-disabled {
  :deep(.el-upload) {
    display: none;
  }
}
</style>
